<?php
/**
 * Created by PhpStorm.
 * User: yy
 * Date: 2019/6/23
 * Time: 16:40
 */

namespace app\common\service\lastWeek;

use think\Db;
use think\facade\Config;
use app\common\service\CommonService;
use DateTime;

/**
 * 上周小结-管控分析
 * Class LastWeekControlAnalysisService
 * @package app\common\service\lastWeek
 */
class LastWeekControlAnalysisService
{
    /**
     * 减排前预报，减排后预报，实测值
     * @author yy by 2019/6/24
     * @param array $param
     * @return array
     */
    public function getReduceForecast($param = [])
    {
        $pollutant_name = str_replace('.', '', strtolower($param['pollutant_name']));
        # 获取减排前预报
        $reduceForecastData = Db::query("select $pollutant_name, DATE_FORMAT(publish_time, '%Y-%m-%d') as date
                                    from air_quality_station_aqi_forecast_day
                                    where region_id = ? and station_id = ? and is_integer = 1 and publish_time = predict_time and DATE_FORMAT(publish_time, '%Y-%m-%d') between ? and ?",
            [$param['region_id'], $param['station_id'], $param['start_time'], $param['end_time']]);
        #实测值
        $realData = Db::query("select $pollutant_name, DATE_FORMAT(publish_time, '%Y-%m-%d') as date
                                    from air_quality_station_aqi_realtime_day
                                    where region_id = ? and station_id = ? and DATE_FORMAT(publish_time, '%Y-%m-%d') between ? and ?",
            [$param['region_id'], $param['station_id'], $param['start_time'], $param['end_time']]);
        # 空数据处理
        $reduceForecastData = $this->getAllData($param, $reduceForecastData, $pollutant_name);
        $realData           = $this->getAllData($param, $realData, $pollutant_name);

        # 减排后预报=减排前预报-预案减排 TODO
        $plan_control_data = 0;
        $reduceLateData    = [];
        $controlData       = [];
        for ($i = 0; $i < count($reduceForecastData['date']); $i++) {
            $reduceLateData['date'][$i]    = $reduceForecastData['date'][$i];
            $reduceLateData['data'][0][$i] = '-';
            # 管控值
            $controlData['date'][$i]    = $reduceForecastData['date'][$i];
            $controlData['data'][0][$i] = 0;
        }
        $result = [
            'reduceForecastData' => $reduceForecastData,
            'reduceLateData'     => $reduceLateData,
            'realData'           => $realData,
            'arr'                => [
                'date' => $controlData['date'],
                'data' => [
                    $reduceForecastData['data'][0],
//                    $controlData['data'][0], //常规管控没有管控值
                    $reduceLateData['data'][0],
                    $realData['data'][0],
                ]
            ],
        ];
        return $result;
    }

    /**
     * 日期补全处理
     * @author yy by 2019/6/24
     * @param array $param
     * @param $data
     * @param $pollutant_name
     * @return mixed
     */
    public function getAllData($param = [], $data, $pollutant_name)
    {
        $commonService = new CommonService();
        $date_all      = $commonService->getDate($param['start_time'], $param['end_time']);
        if (count($data) > 0) {
            $list['date']    = array_column($data, 'date');
            $list['data'][0] = array_column($data, $pollutant_name);
            # 比较差集
            $different     = array_values(array_diff($date_all, $list['date']));
            $different_num = count($different);
            if ($different_num > 0) {
                for ($i = 0; $i < $different_num; $i++) {
                    $list['date'][]    = $different[$i];
                    $list['data'][0][] = '-';
                }
            }
        } else {
            $list['date'] = $date_all;
            for ($i = 0; $i < count($list['date']); $i++) {
                $list['data'][0][$i] = '-';
            }
        }
        # 依据publish_time排序
        array_multisort($list['date'], $list['data'][0]);
        for ($m = 0; $m < count($list['date']); $m++) {
            $list['date'][$m] = date('m/d', strtotime($list['date'][$m]));
            switch ($pollutant_name) {
                case 'aqi':
                    $list['data'][0][$m] = ($list['data'][0][$m] === '-') ? '-' : ceil($list['data'][0][$m]);
                    break;
                case 'co':
                    $list['data'][0][$m] = ($list['data'][0][$m] === '-') ? '-' : round($list['data'][0][$m], 1);
                    break;
                case 'operation_concentration':
                    $list['data'][0][$m] = ($list['data'][0][$m] === '-') ? '-' : round($list['data'][0][$m], 1);
                    break;
                case 'operating_efficiency':
                    $list['data'][0][$m] = ($list['data'][0][$m] === '-') ? '-' : round($list['data'][0][$m] * 100, 1);
                    break;
                default:
                    $list['data'][0][$m] = ($list['data'][0][$m] === '-') ? '-' : $list['data'][0][$m];
            }
        }
        return $list;
    }

    /**
     * 减排后贡献度
     * @author yy by 2019/6/24
     * @param array $param
     * @return array
     * @throws \MongoDB\Driver\Exception\Exception
     */
    public function getReduceAfterContribution($param = [])
    {
        $result = [];
        if (in_array(strtoupper($param['pollutant_name']), ['PM2.5', 'SO2', 'NO2'])) {
            # 减排前预报值
            $before_data = $this->getBeforeContribution($param);

            # 管控值 TODO
            $control_data = [];
            for ($i = 0; $i < count($before_data['date']); $i++) {
                $control_data['date'][$i]    = $before_data['date'][$i];
                $control_data['data'][0][$i] = 0;
            }

            # 减排后预报值 = 减排前预报-预案减排 TODO
            $after_data = [];
            for ($i = 0; $i < count($before_data['date']); $i++) {
                $after_data['date'][$i]    = $before_data['date'][$i];
                $after_data['data'][0][$i] = $before_data['data'][0][$i] - $control_data['data'][0][$i];
            }

            # 实测值
            $real_data = $this->getRealContribution($param);
            $result    = [
                'date' => $before_data['date'],
                'data' => [
                    $before_data['data'][0],
                    $control_data['data'][0],
                    $after_data['data'][0],
                    $real_data['data'][0],
                ]
            ];
        } else {
            $commonService  = new CommonService();
            $date_all       = $commonService->getDate($param['start_time'], $param['end_time']);
            $result['date'] = $date_all;
            for ($i = 0; $i < count($date_all); $i++) {
                $result['date'][$i]    = date('m-d', strtotime($result['date'][$i]));
                $result['data'][0][$i] = ''; //减排前预报值
                $result['data'][1][$i] = ''; //管控值
                $result['data'][2][$i] = ''; //减排后预报值
                $result['data'][3][$i] = ''; //实测值
            }
        }
        return $result;
    }

    /**
     * 减排前预报值
     * @author yy by 2019/6/24
     * @param array $param
     * @return mixed
     * @throws \MongoDB\Driver\Exception\Exception
     */
    public function getBeforeContribution($param = [])
    {
        $commonService     = new CommonService();
        $newTime           = $commonService->getMongoTime($param);
        $companyIdArr      = $commonService->getCompanyIdArr(0);
        $isIndustryId      = $commonService->getIndustryLimitId();
        $mongodb_huanxin   = new \MongoDB\Driver\Manager(Config::get('mongodb_url'));
        $document          = [
            'aggregate'    => Config::get('contribution_table_name'),
            'pipeline'     => [
                [
                    '$project' => [
                        'predict_time'        => 1,
                        'publish_time'        => 1,
                        'contribution_name'   => 1,
                        'company_id'          => 1,
                        'industry_id'         => 1,
                        'station_id'          => 1,
                        'region_id'           => 1,
                        'contribution_value'  => 1,
                        'contribution_degree' => 1,
                        'concentration'       => 1,
                    ],
                ],
                [
                    '$match' => [
                        'industry_id'       => ['$in' => $isIndustryId],
                        'company_id'        => ['$in' => $companyIdArr],
                        'region_id'         => (int)$param['region_id'],
                        'station_id'        => (int)$param['station_id'],
                        'contribution_name' => strtoupper($param['pollutant_name']),
                        'predict_time'      => [
                            '$gte' => $newTime['start_time'],
                        ],
                        'publish_time'      => $newTime['start_time'],
                    ]
                ],
                [
                    '$group' => [
                        '_id'               => ['predict_time' => '$predict_time'],
                        'total'             => ['$sum' => '$contribution_degree'],
                        'concentration_sum' => ['$avg' => '$concentration'],
                    ]
                ],
                [
                    '$sort' => [
                        '_id' => 1,
                    ]
                ]
            ],
            'allowDiskUse' => false,
        ];
        $command           = new \MongoDB\Driver\Command($document);
        $rows              = $mongodb_huanxin->executeCommand('huanxin', $command)->toArray();
        $contribution_data = json_decode(json_encode($rows, 320), true);
        # 日期补全
        $result = $this->dateAll($param, $contribution_data, 1);

        return $result;
    }

    /**
     * 实测值
     * @author yy by 2019/6/24
     * @param array $param
     * @return mixed
     * @throws \MongoDB\Driver\Exception\Exception
     */
    public function getRealContribution($param = [])
    {
        $commonService     = new CommonService();
        $newTime           = $commonService->getMongoTime($param);
        $companyIdArr      = $commonService->getCompanyIdArr(0);
        $isIndustryId      = $commonService->getIndustryLimitId();
        $mongodb_huanxin   = new \MongoDB\Driver\Manager(Config::get('mongodb_url'));
        $document          = [
            'aggregate'    => Config::get('contribution_table_name'),
            'pipeline'     => [
                [
                    '$project' => [
                        'predict_time'        => 1,
                        'publish_time'        => 1,
                        'contribution_name'   => 1,
                        'company_id'          => 1,
                        'industry_id'         => 1,
                        'station_id'          => 1,
                        'region_id'           => 1,
                        'contribution_value'  => 1,
                        'contribution_degree' => 1,
                        'concentration'       => 1,
                        'difference'          => ['$eq' => ['$publish_time', '$predict_time']]
                    ],
                ],
                [
                    '$match' => [
                        'difference'        => true,
                        'industry_id'       => ['$in' => $isIndustryId],
                        'company_id'        => ['$in' => $companyIdArr],
                        'region_id'         => (int)$param['region_id'],
                        'station_id'        => (int)$param['station_id'],
                        'contribution_name' => strtoupper($param['pollutant_name']),
                        'publish_time'      => [
                            '$gte' => $newTime['start_time'],
                            '$lte' => $newTime['end_time'],
                        ],
                    ]
                ],
                [
                    '$group' => [
                        '_id'               => ['predict_time' => '$predict_time'],
                        'total'             => ['$sum' => '$contribution_degree'],
                        'concentration_sum' => ['$avg' => '$concentration'],
                    ]
                ],
                [
                    '$sort' => [
                        '_id' => 1,
                    ]
                ]
            ],
            'allowDiskUse' => false,
        ];
        $command           = new \MongoDB\Driver\Command($document);
        $rows              = $mongodb_huanxin->executeCommand('huanxin', $command)->toArray();
        $contribution_data = json_decode(json_encode($rows, 320), true);
        # 日期补全
        $result = $this->dateAll($param, $contribution_data, 1);
        return $result;
    }


    /**
     * 日期补全
     * @author yy by 2019/6/24
     * @param array $param
     * @param $data
     * @param $is_group
     * @return array
     */
    public function dateAll($param = [], $data, $is_group)
    {
        $list          = [];
        $commonService = new CommonService();
        $date_all      = $commonService->getDate($param['start_time'], $param['end_time']);
        $num           = count($data[0]['result']);
        if ($num > 0) {
            foreach ($data[0]['result'] as $k => $v) {
                $list['date'][]    = date('Y-m-d', $is_group ? strtotime($v['_id']['predict_time']) : strtotime($v['predict_time']));
                $list['data'][0][] = $v['concentration_sum'] > 0 ? $v['total'] / $v['concentration_sum'] : '';
            }
            # 比较差集
            $different     = array_values(array_diff($date_all, $list['date']));
            $different_num = count($different);
            if ($different_num > 0) {
                for ($i = 0; $i < $different_num; $i++) {
                    $list['date'][]    = $different[$i];
                    $list['data'][0][] = '';
                }
            }
        } else {
            $list['date'] = $date_all;
            for ($i = 0; $i < count($list['date']); $i++) {
                $list['data'][0][$i] = '';
            }
        }
        # 依据publish_time排序
        array_multisort($list['date'], $list['data'][0]);
        for ($m = 0; $m < count($list['date']); $m++) {
            $list['date'][$m]    = date('m/d', strtotime($list['date'][$m]));
            $list['data'][0][$m] = $list['data'][0][$m] === '' ? '' : $list['data'][0][$m] * 100;
        }
        return $list;
    }


    /**
     * 按行业查询贡献度
     * @author yy by 2019/6/24
     * @param array $param
     * @return array
     * @throws \MongoDB\Driver\Exception\Exception
     */
    public function getDateIndustryContribution($param = [])
    {
        $list          = [];
        $commonService = new CommonService();
        # 判断 1工业 2非工业
        if ($param['is_industry'] == 1) {
            $arr          = Db::query('select id,name from basic_industry where type = 1 and id <= 4 and delete_time = 0');
            $isIndustryId = array_column($arr, 'id');
        } else {
            $arr          = Db::query('select id,name from basic_industry where type = 2 and delete_time = 0');
            $isIndustryId = array_column($arr, 'id');
        }
        $companyIdArr       = $commonService->getCompanyIdArr(0);
        $param['look_time'] = date('Y-m-d', strtotime($param['look_time'])) . ' 00:00:00';
        # 判断周几 将周日转换成7
        $week      = (date('w') != 0) ? date('w') : 7;
        $week_look = (date('w', strtotime($param['look_time'])) != 0) ? date('w', strtotime($param['look_time'])) : 7;

        # 判断本周关注还是上周小结
        $date = new DateTime();
        $date->modify('this week');
        $first_day_of_week = strtotime($date->format('Y-m-d'));

        if (strtotime($param['look_time']) < $first_day_of_week || $week_look < $week) {
            # 上周小结 和 本周今天之前的查询
            $project = [
                'predict_time'        => 1,
                'publish_time'        => 1,
                'contribution_name'   => 1,
                'company_id'          => 1,
                'industry_id'         => 1,
                'station_id'          => 1,
                'region_id'           => 1,
                'contribution_value'  => 1,//贡献度
                'contribution_degree' => 1,//贡献值
                'concentration'       => 1,
                'difference'          => ['$eq' => ['$publish_time', '$predict_time']]
            ];
            $match   = [
                'difference'        => true,
                'industry_id'       => ['$in' => $isIndustryId],
                'company_id'        => ['$in' => $companyIdArr],
                'region_id'         => (int)$param['region_id'],
                'station_id'        => (int)$param['station_id'],
                'contribution_name' => strtoupper($param['pollutant_name']),
                'predict_time'      => $param['look_time'],
            ];
        } else {
            $project = [
                'predict_time'        => 1,
                'publish_time'        => 1,
                'contribution_name'   => 1,
                'company_id'          => 1,
                'industry_id'         => 1,
                'station_id'          => 1,
                'region_id'           => 1,
                'contribution_value'  => 1,//贡献度
                'contribution_degree' => 1,//贡献值
                'concentration'       => 1,
            ];
            if ((int)date('H') >= 14) {
                $nowTime = date('Y-m-d 14:00:00');
            } else {
                $nowTime = date('Y-m-d') . ' 00:00:00';
            }
            $match = [
                'industry_id'       => ['$in' => $isIndustryId],
                'company_id'        => ['$in' => $companyIdArr],
                'region_id'         => (int)$param['region_id'],
                'station_id'        => (int)$param['station_id'],
                'contribution_name' => strtoupper($param['pollutant_name']),
                'publish_time'      => $nowTime,
                'predict_time'      => $param['look_time'],
            ];
        }
        $mongodb_huanxin    = new \MongoDB\Driver\Manager(Config::get('mongodb_url'));
        $document           = [
            'aggregate'    => Config::get('contribution_table_name'),
            'pipeline'     => [
                [
                    '$project' => $project
                ],
                [
                    '$match' => $match
                ],
                [
                    '$group' => [
                        '_id'               => ['industry_id' => '$industry_id'],
                        'total'             => ['$sum' => '$contribution_degree'],
                        'concentration_sum' => ['$avg' => '$concentration'],
                    ]
                ],
                [
                    '$sort' => [
                        "_id" => 1,
                    ]
                ]
            ],
            'allowDiskUse' => false,
        ];
        $command            = new \MongoDB\Driver\Command($document);
        $rows               = $mongodb_huanxin->executeCommand('huanxin', $command)->toArray();
        $contribution_trend = json_decode(json_encode($rows, 320), true);
        $num                = count($contribution_trend[0]['result']);
        # 钢铁焦化电力(水泥玻璃)id(水泥玻璃行业在一起20190611)
        if ($num > 0) {
            foreach ($contribution_trend[0]['result'] as $k => $v) {
                foreach ($arr as $k2 => &$v2) {
                    if ($v2['id'] == $v['_id']['industry_id']) {
                        $list['date'][] = $v2['name'];
//                        $list['data'][0][] = $v['concentration_sum'] > 0 ? $v['total'] / $v['concentration_sum'] * 100 : '';
                        $list['data'][0][] = $v['concentration_sum'] > 0 ? $commonService->contributionRound($v['total'] / $v['concentration_sum']) : '';
                    }
                }
            }
        } else {
            foreach ($arr as $k => $v) {
                $list['date'][]    = $v['name'];
                $list['data'][0][] = ''; //各个行业的单天贡献度都为'';
            }
        }
//        sort($list['data']);
        return $list;
    }

}